from datetime import datetime, timedelta
import os
import threading
import time
import tkinter as tk
import sys
from tkinter import messagebox
from tkinter import ttk

import gui_util.gui_common as gui_common
import user_manager.user_manager as user_manager
from gui_util.login_window import LoginWindow


# 主窗口关闭时，设置退出标志
def on_closing(window: tk.Tk):
    global usession
    usession.stop_event.set()
    # 可能还需要调用thread.join()来等待线程结束，但这会阻塞主窗口关闭，需谨慎使用
    window.destroy()  # 假设root是你的Tkinter窗口实例


# 主窗口关闭时，设置退出标志
def on_query_window_closing(window: tk.Toplevel):
    global chat_client
    chat_client.query_tree_selected = None
    window.destroy()


usession = user_manager.UserSession()


prev_selection = None  # 初始化上一个选中项变量
prev_selection_tag = None


def on_select(event, treeview: ttk.Treeview):
    try:
        # 获取当前选中项的ID
        current_selection = treeview.selection()
        global prev_selection
        global prev_selection_tag
        # 检查并处理已删除的前一个选中项
        if prev_selection and not treeview.exists(prev_selection):
            prev_selection = None
            prev_selection_tag = None

        # 如果有之前选中的项，恢复其背景色
        if prev_selection and treeview.exists(prev_selection):
            treeview.item(prev_selection, tags=prev_selection_tag)
            usession.check_item_onoffline(prev_selection[0])

        # 设置当前选中项的标签
        if current_selection:
            prev_selection_tag = treeview.item(current_selection, "tags")
            treeview.item(current_selection, tags=("selected",))
            # 记录当前选中项以便下次切换
            prev_selection = (
                current_selection  # 注意，selection可能返回多个项目，这里取第一个
            )
    except Exception as e:
        print(f"Error during selection: {e}")


def on_treeview_motion(event, tooltip: gui_common.TreeToolTip, tree: ttk.Treeview):
    item = tree.identify_row(event.y)
    if item:
        tooltip.showtip(event, usession.get_item_tool_tip(item))
    else:
        tooltip.hidetip()


class ChatClient:
    def __init__(self, usession):
        self.usession: user_manager.UserSession = usession
        self.app = tk.Tk()
        self.app.title("ChatClient")
        self.usession.root_window = self.app
        self.user_list_frame = None
        self.user_list_tile = None
        self.user_tree_frame = None
        self.user_list_scrollbar = None
        self.user_tree = None
        self.recv_frame = None
        self.recv_title_label = None
        self.recv_inner_frame = None
        self.recv_scrollbar = None
        self.recv_text = None
        self.send_frame = None
        self.send_title_label = None
        self.send_text = None
        self.query_tree_selected = None
        self.last_query_all_user_time: datetime = None

    def send_tcp_data(self):
        content = self.send_text.get("1.0", "end-1c")  # "end-1c"用于排除末尾的换行符
        if not content:
            messagebox.showerror("输入错误", "请输入要发送的数据")
            return
        else:
            current_selection = self.user_tree.selection()
            if current_selection:
                usession.send_chat_msg(current_selection[0], content)
                # 清空文本并更新界面
                self.send_text.delete("1.0", tk.END)
                self.send_text.update_idletasks()

                # 使用after方法在下一个事件循环周期设置光标，确保界面更新完成
                self.send_text.after(
                    0,
                    lambda: [
                        self.send_text.mark_set(tk.INSERT, "1.0"),  # 设置光标到起始位置
                        self.send_text.see(tk.INSERT),  # 确保光标位置可视
                        # 下面的步骤是为了确保失去并重新获得焦点的操作有效
                        self.send_text.master.focus_set(),  # 失去焦点
                        self.send_text.after(
                            1, self.send_text.focus_set
                        ),  # 稍后重新获得焦点
                    ],
                )
            else:
                messagebox.showerror("错误", "请选择一个好友")
                return

    def send_textbox_focus_in(self, event):
        # 获取文本框当前的所有文本
        content = self.send_text.get("1.0", "end")
        # 检查文本的最后一字符是否为换行符
        if content.endswith("\n"):
            # 删除最后一个字符（换行符）
            self.send_text.delete("end-2c", "end")

    def create_gui(self):
        self.user_list_frame = tk.Frame(
            self.app,
            padx=0,
            pady=0,
        )
        self.user_list_frame.grid(
            row=0, column=0, padx=2, pady=(2, 0), sticky=tk.NSEW
        )  # 设置外边距以控制紧凑度

        self.user_list_tile = tk.Label(
            self.user_list_frame,
            text="tcp_connections",
            font=("Arial", 14, "bold"),
            fg="blue",
            width=26,
        )
        self.user_list_tile.pack(
            side=tk.TOP,
            fill=tk.BOTH,
        )

        self.user_tree_frame = tk.Frame(
            self.user_list_frame,
            padx=0,
            pady=0,
        )
        self.user_tree_frame.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
        #     # 创建一个垂直滚动条
        self.user_list_scrollbar = ttk.Scrollbar(self.user_tree_frame)
        self.user_list_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.create_user_tree()
        self.user_list_scrollbar.config(command=self.user_tree.yview)

        self.create_recv_frame()  # 第一列 权重是1
        self.app.columnconfigure(1, weight=1)

        self.create_send_frame()
        self.create_btn_frame()
        self.app.rowconfigure(0, weight=1)
        self.app.rowconfigure(1, weight=2)
        self.usession.set_info_tree(self.user_tree, self.recv_text)
        print("create_gui")

    def click_btn_modify(self):
        if not self.usession.is_logged_in:
            messagebox.showerror("错误", "用户还没有登录")
        else:
            gui_common.show_edit_window(
                self.app,
                self.usession.user_id,
                self.usession.user_name,
                self.usession.pwd,
            )

    def btn_close_tcp_conn(self):
        if self.usession.is_connected:
            self.usession.disconnect()
        else:
            messagebox.showerror("错误", "没有连接")

    def create_btn_frame(self):
        # # 创建一个Frame来包裹按钮，便于控制它们的紧凑排列
        self.frame_btn = tk.Frame(self.app, padx=0, pady=0)
        self.frame_btn.grid(row=1, column=0, pady=(0, 2), sticky=tk.N)
        self.info_tree_item_id = self.user_tree.insert(
            "",
            tk.END,
            values=(self.usession.connection_string, "connected"),
            tags=("connected"),
        )
        self.usession.info_tree_item_id = self.info_tree_item_id
        self.user_tree.set(self.info_tree_item_id, "connStatCol", "loggedin")
        self.user_tree.set(self.info_tree_item_id, "UserName", self.usession.user_name)
        self.user_tree.item(self.info_tree_item_id, tags=("loggedin",))
        # 创建一个按钮
        self.btn_close = tk.Button(
            self.frame_btn, text="关闭连接", command=self.btn_close_tcp_conn
        )
        self.btn_close.grid(row=0, column=0, padx=2, pady=0)
        self.btn_modify = tk.Button(
            self.frame_btn, text="信息修改", command=self.click_btn_modify
        )
        self.btn_modify.grid(row=0, column=1, padx=10, pady=10)

        # # 创建一个按钮
        self.btn_send = tk.Button(
            self.frame_btn,
            text="发送数据",
            command=self.send_tcp_data,
        )
        self.btn_send.grid(row=0, column=2, padx=2, pady=0)
        self.send_text.bind("<Return>", lambda event: self.btn_send.invoke())
        self.send_text.bind("<FocusIn>", self.send_textbox_focus_in)

        # 创建一个查询按钮
        self.btn_query = tk.Button(
            self.frame_btn, text="查询用户", command=self.create_query_window
        )
        self.btn_query.grid(row=0, column=3, padx=2, pady=0)

    def create_query_window(self):
        if not self.usession.is_connected:
            messagebox.showerror("错误", "没有连接")
            return
        if not self.usession.is_logged_in:
            messagebox.showerror("错误", "用户还没有登录")
            return
        self.query_window = tk.Toplevel(self.app)
        self.query_window.title("用户列表")
        gui_common.center_window(self.query_window, 400, 300)
        query_tree_frame = tk.Frame(self.query_window)
        query_tree_frame.grid(row=0, column=0, padx=2, pady=2, sticky=tk.NSEW)
        self.query_window.grid_columnconfigure(0, weight=1)
        self.query_window.grid_rowconfigure(0, weight=1)
        self.query_window.protocol(
            "WM_DELETE_WINDOW", lambda: on_query_window_closing(self.query_window)
        )

        # 创建 Treeview 控件
        self.query_tree = ttk.Treeview(
            query_tree_frame, columns=("col1", "col2", "col3"), show="headings"
        )
        self.query_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.query_tree.heading("col1", text="好友ID")
        self.query_tree.heading("col2", text="好友名称")
        self.query_tree.heading("col3", text="状态")
        self.query_tree.column("col1", width=50, stretch=tk.YES)
        self.query_tree.column("col2", width=50, stretch=tk.YES)
        self.query_tree.column("col3", width=50, stretch=tk.YES)

        self.query_tree["displaycolumns"] = ("col1", "col2", "col3")  # 显示列标题
        self.usession.configure_tags(self.query_tree)

        if len(self.usession.all_users) > 0:
            current_time = datetime.now()
            if current_time - self.last_query_all_user_time > timedelta(seconds=5):
                self.last_query_all_user_time = datetime.now()
                self.usession.req_user_list(True)
                self.usession.all_user_list_event.wait()
            self.add_alluser_to_tree()
        else:
            self.last_query_all_user_time = datetime.now()
            self.usession.req_user_list(True)
            self.usession.all_user_list_event.wait()
            self.add_alluser_to_tree()

        query_tree_scrollbar = ttk.Scrollbar(query_tree_frame)
        query_tree_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        query_tree_scrollbar.config(command=self.user_tree.yview)

        btn_add_user = tk.Button(
            self.query_window, text="添加好友", command=self.add_friend
        )
        btn_add_user.grid(row=1, column=0, padx=2, pady=2)

    def add_alluser_to_tree(self):
        for id, user in self.usession.all_users.items():
            item_id = self.query_tree.insert(
                "",
                tk.END,
                values=(
                    user.user_id,
                    user.user_name,
                    "在线" if user.online else "离线",
                ),
                tags=("online" if user.online else "offline",),
            )
            user.info_tree_item_id = item_id
            self.usession.all_itemid_user[item_id] = user

    def add_friend(self):
        query_tree_selection = self.query_tree.selection()
        if query_tree_selection:
            user_id = self.usession.all_itemid_user[query_tree_selection[0]].user_id
            if user_id == self.usession.user_id:
                messagebox.showerror("错误", "不能添加自己为好友")
                return
            if user_id in self.usession.friend_id_list:
                messagebox.showerror("错误", "已经是好友")
                return
            self.usession.handle_add_friend_req(user_id)
        else:
            messagebox.showerror("错误", "请选择好友")

    def create_user_tree(self):
        self.user_tree = ttk.Treeview(
            master=self.user_tree_frame,
            columns=("UserName", "connStatCol"),
            show="headings",
            selectmode="browse",
            yscrollcommand=self.user_list_scrollbar.set,
        )
        self.user_tree["displaycolumns"] = ("UserName", "connStatCol")  # 显示列标题
        self.user_tree.heading("UserName", text="用户", anchor=tk.W)  # 设置列标题
        self.user_tree.heading("connStatCol", text="状态", anchor=tk.W)
        self.user_tree.tag_configure(
            "selected", background="lightyellow"
        )  # 定义一个tag来改变颜色
        self.user_tree.column("UserName", width=100, stretch=tk.YES)  # 第一列固定宽度
        self.user_tree.column("connStatCol", width=50, stretch=tk.YES)  # 第一列固定宽度
        self.user_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.user_tree.bind(
            "<<TreeviewSelect>>", lambda event: on_select(event, self.user_tree)
        )  # 绑定选择事件
        # 初始化Tooltip实例
        treetooltip = gui_common.TreeToolTip(self.user_tree)
        # 绑定鼠标移动事件以显示/隐藏Tooltip
        self.user_tree.bind(
            "<Motion>",
            lambda event: on_treeview_motion(event, treetooltip, self.user_tree),
        )

        self.right_btn_menu = tk.Menu(self.user_tree, tearoff=0)
        self.right_btn_menu.add_command(label="删除", command=self.delete_node)
        # 绑定右键点击事件
        self.user_tree.bind("<Button-3>", self.pop_right_btn_menu)

    def delete_node(self):
        # 获取当前选中的节点
        selected_item = self.user_tree.selection()
        if selected_item:
            # 删除选中的节点
            # self.user_tree.delete(selected_item)
            # 删除对应的好友信息
            itemid = selected_item[0]
            info = self.usession.friend_list[itemid]
            if messagebox.askyesno(
                "删除", f"是否删除好友 {info.user_name} ID{info.user_id}？"
            ):
                del self.usession.friend_id_list[info.user_id]
                del self.usession.friend_list[itemid]
                global prev_selection
                # 如果即将删除的节点是当前选中的节点，先清除它
                if prev_selection == selected_item:
                    prev_selection = None
                self.user_tree.selection_remove(selected_item)  # 移除选中状态
                self.user_tree.delete(selected_item)  # 删除节点
        else:
            messagebox.showerror("错误", "请选中好友")

    def pop_right_btn_menu(self, event):
        # 获取鼠标点击位置的item_id
        item_id = self.user_tree.identify_row(event.y)
        if item_id:
            # 显示右键菜单
            self.right_btn_menu.post(event.x_root, event.y_root)
        else:
            # 隐藏右键菜单
            self.right_btn_menu.unpost()

    def create_recv_frame(self):
        # 配置grid布局的列，让第1列自动扩展填充可用空间
        self.recv_frame = tk.Frame(self.app, padx=0, pady=0)
        self.recv_frame.grid(row=0, column=1, padx=2, pady=(2, 0), sticky=tk.NSEW)

        # # 确保recv_title_label显示在recv_text上方
        self.recv_title_label = tk.Label(
            self.recv_frame,
            text="recv_message",
            font=("Arial", 14, "bold"),
            fg="blue",
            anchor=tk.W,
        )
        self.recv_title_label.pack(
            side=tk.TOP, fill=tk.BOTH
        )  # 保持此处不变，标题横跨宽度

        # # 内部Frame用于放置滚动条和Text
        self.recv_inner_frame = tk.Frame(self.recv_frame)
        self.recv_inner_frame.pack(
            side=tk.BOTTOM, fill=tk.BOTH, expand=True
        )  # 修改为side=tk.TOP以使内部Frame位于顶部

        # # 创建滚动条，并将其放置在内部Frame
        self.recv_scrollbar = tk.Scrollbar(self.recv_inner_frame)
        self.recv_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 将滚动条与recv_text关联
        self.recv_text = tk.Text(
            self.recv_inner_frame,
            wrap=tk.WORD,
            yscrollcommand=self.recv_scrollbar.set,
            spacing1=5,
        )
        self.recv_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        # 配置滚动条的行为
        self.recv_scrollbar.config(command=self.recv_text.yview)

    def create_send_frame(self):
        self.send_frame = tk.Frame(self.app, padx=0, pady=0)
        self.send_frame.grid(
            row=1, column=1, sticky=tk.NSEW, pady=(0, 10), padx=(0, 10)
        )
        self.send_title_label = tk.Label(
            self.send_frame,
            text="send_message",
            font=("Arial", 14, "bold"),
            fg="blue",
            anchor=tk.W,
        )
        self.send_title_label.pack(side=tk.TOP, fill=tk.BOTH)
        self.send_text = tk.Text(self.send_frame, wrap=tk.WORD, spacing1=5)
        self.send_text.pack(fill=tk.BOTH, expand=True)

    def show(self):
        gui_common.center_window(self.app, 1000, 400)
        self.app.protocol("WM_DELETE_WINDOW", lambda: on_closing(self.app))
        self.app.mainloop()


if __name__ == "__main__":
    try:
        login_window = LoginWindow(usession)
        usession.login_window = login_window
        login_window.show()
        if usession.is_logged_in:
            chat_client = ChatClient(usession)
            chat_client.create_gui()
            usession.handle_login_success()
            usession.req_user_list()
            chat_client.show()
    except Exception as e:
        print(e)
